perm filename MEMO61.PUB[HAL,HE] blob sn#117121 filedate 1974-08-28 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00019 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	.NEWSEC SOURCE LANGUAGE,COMPILER
C00010 00003	.NEWSS (CONTROL STRUCTURES,CONTROL STRUCTURES)
C00015 00004	.tsk:NEWSSS PARTIAL ORDERING OF SUBTASKS
C00021 00005	.onm: NEWSSS ON MONITORS
C00029 00006	.NEWSSS UNITS
C00035 00007	.NEWSSS	PROCEDURES
C00041 00008	.NEWSS (DATA STRUCTURES,DATA STRUCTURES)
C00046 00009	.dat: NEWSSS	ALGEBRAIC DATATYPES
C00055 00010	.NEWSSS	ARITHMETIC
C00061 00011	.NEWSSS	SOME EXAMPLES OF ARITHMETIC EXPRESSIONS
C00063 00012	.NEWSS MOTIONS
C00072 00013	.NEWSSS	OPTIONS FOR MOVES
C00081 00014	.dep: NEWSSS DEPROACHES
C00089 00015	.NEWSSS	COMPLEX MOVES
C00094 00016	.NEWSSS SEARCHES
C00100 00017	.NEWSSS DEVICE CONTROL
C00105 00018	.att: NEWSS ATTACHMENT
C00111 00019	.gph:NEWSS GRAPH STRUCTURES
C00119 ENDMK
C⊗;
.NEWSEC SOURCE LANGUAGE,COMPILER

	The following is a description of the source language of HAL.
We will discuss the structure of the compiler, and then these areas of
the  language:  control  structures,     data  structures,     motion
specifications, and various compile time constructs.

.com: NEWSS THE HAL COMPILER

The HAL compiler is built of three parts: the parser, the expander,
and the trajectory calculator.  These are depicted in
{NEWFIG The HAL compiler,FULL,com←}.

.NEWSSS PARSER

	The PARSER  reads source code  from either  the console or  a
file.    Its  purpose is  to  form  parse trees  and  do  some simple
manipulations,  such as assigning line numbers,  causing  listings to
be  directed to  the appropriate  file (if  desired), expanding  text
macros,   and keeping a primitive symbol table.  If a syntax error is
discovered,  it  informs the  supervisor,  which  will give the  user
several  options,  including  aborting the compilation,  making local
modifications on  the  spot,   or  switching temporarily  to  a  text
editor.  In many cases,  control will be returned to the parser,  and
it will continue to create parse trees from the input.

.NEWSSS EXPANDER  
  
The EXPANDER shares with the trajectory calculator the responsibility
for turning parser output into code interpretable by the runtime
system.  Its main functions are to maintain a model of the
expected runtime state at each point in the program and to use this
model to resolve a number of compile-time decisions.  The information
kept includes expected variable values,
object descriptions, relations
between objects, endpoint constraints on particular trajectories, and
much more.  Simple uses of this information include providing
the trajectory calculator with essential data and resolving
conditional compilation requests.  Beyond this, the expander
has principal responsibility for filling in the details required
to turn calls on various high and intermediate level primitives
into runnable manipulation programs.  It therefore
contains a number of quite specialized routines with considerable
knowledge about the domain of mechanical assembly, as well as a number
of more general mechanisms for coordinating the specialists.

The expander supplies to the trajectory calculator a structure which is
very similar to the parse trees it
accepts as input.  However, no choices are left; all values have been
explicitly specified.

.NEWSSS TRAJECTORY CALCULATOR

	The  TRAJECTORY  CALCULATOR  takes  the   expanded  code  and
computes  the  required   trajectories  for  the  arms.    Tables  of
interpretable  code are  generated    for  handling  arithmetic  and
assignment operations,   condition  monitoring,   and graph-structure
building  operations  (the  runtime system  keeps  track  of physical
attachment of  objects).   For  motions,   detailed instructions  are
emitted specifying  how each joint  of each arm  is to behave,   what
computations to  make  at  run-time for  the  modification  of  these
trajectories to bring them into correspondence with the current state
of the world (for it happens often that objects are not exactly where
they were planned to be),  and what conditions to monitor during  the
motion.

	The trajectory calculator also is used to provide information
to the expander.   For instance,  it can  predict the runtime effects
of a given modification of a planned trajectory.  This information is
useful to the expander in deciding  how many "different" trajectories
must be planned for a given motion request.
	There are  several errors which the trajectory calculator can
detect.  A request might take  the arm outside its range, or force  a
joint to exceed its velocity limits.  It may discover that there is a
possibility of collision between the two arms,  or between the arm and
some object on the table.  In order to carry out these tests,  it may
request  assurance  from the  user  that some  object  lies within  a
certain region,  or it may give the user a warning.  The world  model
is  used for  much  of  this calculation.    At its  discretion,  the
trajectory calculator  may make some critical motions  very slow,  so
that an impending collision will be detected before it happens. 

	The output of the  trajectory calculator is stored in  binary
files,  for loading into the PDP11.
.NEWSS (CONTROL STRUCTURES,CONTROL STRUCTURES)

.NEWSSS TRADITIONAL ALGOL STRUCTURES

	HAL has  many of  the traditional  ALGOL control  structures,
including the  statement,  the block,   the IF-THEN-ELSE conditional,
the WHILE loop, the FOR loop,  and the GOTO (which in HAL  is written
JUMP. JUMPs  will not be  implemented at first, because  they confuse
the flow analysis needed for maintaining planning values and because
it  is  possible to  accomplish  much  without  them).    The  simple
statement  can  be  of  several varieties:  Assignment,  declaration,
manipulation, assertions,    condition  monitoring.   The
assignment statement is of the general form 
.UNFILL 
	FROB α← A  +  (2,0,0)     ,  
.REFILL
that is, a variable name,  a left arrow,   and a suitable expression.
The types of expressions available will be discussed under the rubric
of data types.   Declarations are allowed  anywhere in the code  that
other statements  are allowed; this  facilitates typing in  a program
from a  terminal. Manipulation, the fundamental purpose of HAL,  will
be discussed fully  in the section  on motion specifications.   
Assertions are discussed in {sssref asr}.
Condition monitoring is discussed in {sssref onm}.

A block  is  a list  of statements  separated by  semicolons,
prefaced by  the reserved word BEGIN and  closed by the reserved word
END.  Blocks are used to  enclose a group of statements to form  what
syntactically  can act  as one  statement,  and provide  a means  for
keeping variables local to a piece of code.  It is possible to name a
block by  inserting its name  as a  string after  the BEGIN; this  is
useful  as a comment,  and during  debugging provides  a way  to name
blocks of code. When a block is so named, the name should be repeated
immediately after the END; this provides an easy way to insure proper
matching of BEGINs and ENDs. An example:
.UNFILL
	BEGIN "SAMPLE"
	SCALAR A, I;
	A α← 2;
	FOR I α← 1 STEP 1 UNTIL 10 DO A α← A*A;
	WHILE A > 0 DO
		BEGIN "LOOP"
		A α← A - 1;
		IF A < 5 THEN WRITE(A) ELSE WRITE(A-5)
		END "LOOP";
	WRITE("DONE")
	END "SAMPLE"

.REFILL
.NEWSSS	COBEGIN-COEND

	In addition to  these traditional structures, there  are also
some special  ones for specifying simultaneous independent execution.
The principal  device for  this  is the  COBEGIN-COEND pair,    which
brackets statements whose execution is meant to begin independently.
Each  of the statements within the  COBEGIN block will eventually get
executed, with whatever  overlapping of execution might  occur during
runtime (for example, while  one arm is moving, another statement can
be computing; several arms can  also work at the same time). The  termination
of the block occurs only when each of the  statements in the scope of
the COBEGIN has terminated.

.tsk:NEWSSS PARTIAL ORDERING OF SUBTASKS

	An assembly task is often divided into  subtasks which form a
partial order with  respect to the order of execution.  An example is
a task A which contains four subtasks, B, C, D, and E, of which B and
C must  be done before D,  and D must be  done before E, but  B and C
could  be done  in any  order.  It  is possible  in HAL  to leave the
ordering of  the  subtasks up  to  the compiler,  which will  try  to
optimize the entire  operation.  The way to  specify the example just
given is as follows:
.UNFILL
	TASK BEGIN "A"
		BEGIN "B"
		<code for task B>
		END "B";

		BEGIN "C"
		<code for task C>
		END "C";

		BEGIN "D AND E"
		PREREQUISITE "B", "C";
		<code for task D>
		<code for task E>
		END "D AND E"
	END "A"
.REFILL

	The words TASK BEGIN introduce a  "task block", which contains
a  set of statements.  These statements  may be  blocks identified by
strings and  may contain  the declaration  that  certain other  named
blocks within  the same  task are prerequisite  for the  inception of
this block.

	The order in which the statements are performed is determined
only insofar as the prerequisite conditions demand.  The compiler may
reorder them consistently with  the preconditions, and may even execute
some of the statements simultaneously  (as if there were a  COBEGIN),
if this is feasible.

	It is useful to place assertions at the beginning of the code
for any of the statements within a task; this assists the compiler in
maintaining its  world model, and  is also  used to  help decide  the
proper ordering of the tasks. It is likewise good to place assertions
at the end of each statement. (Assertions are discussed in {sssref asr}.)

.NEWSSS	EVENTS:  SIGNAL AND WAIT

	To  achieve simultaneous  coordinated  motion,   one  uses  a
special  form of  the move  commands which  will be  discussed later.
However, some  simple  synchronization  is  possible within  the  context  of
simultaneous  execution.   This  is  achieved  by means  of  explicit
events,  which can be signaled and awaited.   For every type of event
that the user wishes to use, there should be  a declaration something
like:
.UNFILL
	EVENT E1, E2, E3     .
.REFILL
Each event initially has  count 0, that is, no  signals have appeared
for it, and no process is waiting for it.  The statement
.UNFILL
	SIGNAL E1
.REFILL
increments the count associated  with event E1, and if  the resulting
count  is 0  or negative, one  of those  processes waiting for  E1 is
freed from its wait and readied for execution.  The statement
.UNFILL
	WAIT E1
.REFILL
decrements the count associated  with event E1, and if  the resulting
count  is negative,  the  process issuing  the WAIT  is  blocked from
continuing until  a  signal  comes along.    If  the count  is  0  or
positive, there is no waiting.

	An  example of  the utility  of  this construct  is inside  a
COBEGIN  block, where one  path of execution requires  that the other
path has passed some milestone.  Here is how such a use might appear:
.UNFILL
	EVENT MILESTONE;
	COBEGIN
		BEGIN "PATH 1"
		<code before the critical point>
		WAIT MILESTONE;
		<code after the critical point>
		END "PATH 1";

		BEGIN "PATH 2"
		<code in preparation for the milestone>
		SIGNAL MILESTONE;
		<code following the milestone>
		END "PATH 2"
	COEND 
.REFILL
.onm: NEWSSS ON MONITORS

	It  is  often  desired to  monitor  some  set  of  conditions
throughout a section of code.  A special kind of statement which allows
the user to do this is the ON statement.  A simple example is 
.UNFILL
	ON T >5 DO STOP YELLOW
.REFILL
 which while active will monitor the magnitude of T
and  if it should become greater than 5  will cause the yellow arm to
stop, if it  is moving.   An ON monitor  has two states: enabled  and
disabled. Generally,   an ON monitor  will be enabled as  soon as its
defining statement is  executed,   and it becomes  disabled when  its
block is exited. Also, as soon as an  ON monitor triggers, it becomes
disabled until explicitly reenabled.  Reenabling is done by executing
the statement ENABLE within the  conclusion (that is,  the  statement
following the  DO).  It  is possible to  name ON monitors;  a monitor
named  "CH" will be enabled when a  statement of the form ENABLE "CH"
is executed, and is disabled either under the  conditions named above
or when it is explicitly  turned off by a DISABLE statement.  To have
an ON monitor initially disabled, preface the ON with the word DEFER.  

	The condition which is being tested must  be a simple numeric
inequality  or equality,  possibly  using some  continually evaluated
function.  Boolean combinations are not allowed.
	Some examples of ON monitors:
.UNFILL
	"FUDGE" ON TEMPERATURE > 400 DO WRITE("BURNING");
	DEFER "WAIT" ON COOKED = 1 DO DISABLE "FUDGE";
	ON MARK > 3 DO ENABLE "WAIT";
.REFILL
	It should be  noted that this  ability to enable  and disable
monitors explicitly is  a non-structured concept; using it will often
lead to unintelligible programs.   In any  case, scope rules must  be
observed;  it is  not  legal to  enable  or disable  a  monitor in  a
parallel  or  subsidiary  block.  This  means  that  two  statements,
simultaneously executing inside a  COBEGIN block, are not  allowed to
interfere with each other's ON monitors.
	The  conclusion  of  an  ON-monitor  may  be  any  statement,
including  an entire block.   The only restriction is  that if a motion
statement is  the  only  statement  in the  conclusion,  it  must  be
surrounded by BEGIN and END.   (This is necessary at times to prevent
ambiguity.)  Here is a slightly more complex example:
.UNFILL

	ON DURATION > 5 DO
		BEGIN
		"BIND" ON FORCE(Z)>10 DO STOP YELLOW;
		ON DIST > 3 DO 
			BEGIN
			DISABLE BIND;
			VEL α← 40
			END
		END

.REFILL
	The existence of ON monitors raises this question: When is a
block  considered  to  be  finished?  It  can  happen that  all  the
executable statements have  finished,  but  some ON monitors  remain.
This situation is often sterile; nothing can happen unless one of the
conditions  happens  to  trigger,    which  may  or  may not  ever occur.
Therefore,  a block is declared finished when  no interpreters
(that is, pieces of straightforward code, exclusive of on-monitors)
 remain
active within it.  This  means that if even one ON monitor has caused
an interpreter to start executing  (to perform the statements in  the
conclusion), then the block  is not exited until that  interpreter is
done.   But a block  may be exited  while some ON  monitors are still
enabled; this automatically disables them.

	The  user must be  wary of the  relative speeds  at which her
various pieces of code in ON test conclusions get executed.   When an
ON test triggers, any initial statements of enabling or disabling are
done immediately,  but any arithmetic is scheduled to be done at some
point in the near future.  Therefore it is  not possible to guarantee
that a critical computation happen immediately.  If the user desires,
she may use  the word CRITICAL  at the start  of the conclusion,  and
UNCRITICAL at  the start of  that code which  need not  be guaranteed
immediate  execution. 
Only one occurrence of CRITICAL, at the very start of the conclusion,
and only one occurrence of UNCRITICAL are allowed.
   HAL  automatically  assumes CRITICAL  before
statements of  enabling and  disabling,   and UNCRITICAL  immediately
following.     
An example:
.UNFILL
	ON T>0 DO
		BEGIN "CONCLUSION"
		ENABLE "GOOD GUY";	COMMENT:  Assumed CRITICAL;
		T α← 3;			 COMMENT:  Assumed UNCRITICAL;
		END "CONCLUSION";
	ON S<0 DO
		BEGIN "RESULT"
		CRITICAL;  		COMMENT:  Overrides defaults;
		T α← 4;			COMMENT:  Will be done immediately;
		UNCRITICAL;		COMMENT:  End of critical region;
		DISABLE "GOOD GUY";	COMMENT:  Done eventually;
		END "RESULT"
.REFILL

.NEWSSS UNITS

	Numbers  are quite  often  used  for measurements,  and  many
different systems  of measurement exist.  The  UNITS statement serves
to inform the compiler which units are  being used.  The compiler uses its  own
system for internal consistency, and does any scaling when necessary.
The default  units, which the compiler itself  uses, are placed first
in the following lists:
.UNFILL
Time:		milliseconds, seconds, jiffies (that is, thirds: 60ths
		  of a second), minutes.
		  (The grain of the runtime is on the order of jiffies).
Distance:	centimeters, inches.
Mass:		grams, ounces, pounds, kilograms.
Angles:		radians, degrees.
Rotations:	Euler, Bolles, Taylor, Geomed. (These are explained
		  in {sssref dat}.)

	An example:
	UNITS SECONDS, DEGREES, TAYLOR;
.REFILL

.NEWSSS	COMMENTS

	As in Algol, comments are prefaced with  the word COMMENT and
terminated by a semicolon. Also, any text enclosed in curly brackets,
as in 
.UNFILL
	α{We are the hollow menα}
.REFILL
will be ignored.  The user can optionally reset the comment delimiters
from "α{α}" to whatever she wishes, by means of a require statement
such as:
.UNFILL
	REQUIRE "α%α%" COMMENT_DELIMITERS       .
.REFILL
which would cause the scanner to ignore any text between "α%" signs.

.NEWSSS	LABELS

	A LABEL  is a point  in the  program to which  a jump may  be
made.  Labels are not declared. An
example:
.UNFILL
	FOO: A α← A + 1;
	IF A < 100 THEN JUMP FOO; 
.REFILL
Labels  are in  general  useful mainly  for  debugging, and  not  for
program  control, especially  since JUMP will  not be  implemented at
first.

.NEWSSS ABORT

	Occasionally the user wishes to stipulate that if the program
ever reaches a particular point, something is hopelessly wrong.  The
statement ABORT causes the runtime to stop all moving devices and
to terminate execution.  The supervisor is informed of the halt, and
will inform the user. ABORT takes an optional string argument, which
is a message which will be given to the user if the ABORT statement
is executed.  An example:
.UNFILL
	ABORT ("I KEEP MISSING THE BOLT!")
.REFILL

.NEWSSS OUTPUT

	There are several ways that the user can request output
from HAL to the console.  As mentioned above, ABORT can print
a message during execution.  There is one other way to print a
message during execution, the WRITE statement, which
takes as arguments a list of variables and constants.
It is also legal to include a string constant in this list (there
are no string variables in HAL).  Formatting of output is automatic.
An example:
.UNFILL
	WRITE ("I think that the pump is at ",PUMP)
.REFILL

	Some pieces of code are only intended to work under
certain conditions of planning knowledge.  Such code might 
have a check to insure that its preconditions are met; if not,
it is proper to signal a compile-time error, with a message.
This is done with the COMPILE_ERROR statement, which optionally
takes a string argument, and which will halt compilation and print
the message.  One of the options the supervisor will give the user
is to proceed as if no error had been encountered.  Here is
an example:
.UNFILL
	COMPILE_ERROR("Hey!  You didn't attach the pump to the hand!")
.REFILL

	A similar statement which merely prints its message but
does not halt compilation is the COMPILE_WRITE statement, which
behaves in all respects like the runtime WRITE statement, in that
it can take variables and constants in its argument list, but where
variables are specified, the planning values will be printed.  For
example:
.UNFILL
	COMPILE_WRITE("YELLOW arm should be at",YELLOW)
.REFILL
.NEWSSS	PROCEDURES

	HAL  has  only   a  limited  capacity  for   procedures.  All
parameters  to a procedure  assume the planning  value "undefined" at
the conclusion of a procedure  call, except those which are  declared
as VALUE parameters  in the procedure heading, or those  stated to be
UNCHANGED  in the procedure  call. There is no  safeguard against the
accidental   modification  of  "unchanged"   parameters;   to   state
"unchanged" is entirely equivalent to an assertion that the parameter
has not changed its value during the execution of the procedure.  The
declaration of a procedure is this:
.UNFILL
	 type  PROCEDURE name (argument list)     ,
.REFILL
where  "type" is any datatype (and  is optional), and "argument list"
is a list of parameter names with their types.  An example:
.UNFILL
	SCALAR PROCEDURE LGTH (FRAME F1, F2; VECTOR VALUE V1);
.REFILL
This  declares that  LGTH is a procedure which returns  a scalar, and
takes as arguments two frames and one vector.  The vector is not
changed by the procedure.

	To call such a procedure:
.UNFILL
	S1 α← LGTH(FROB, UNCHANGED HOLE, VECT);
.REFILL
This further asserts that HOLE is not changed by the call.

	Assertions are essential at the start of  a procedure body to
inform  the  compiler  of  the  values  to  expect  for  the  various
arguments. Remember that trajectories planned on the basis  of highly
inaccurate planning values will not work well.
Assertions are discussed in {sssref asr}.

	As a procedure is entered,  all variables have planning value
"undefined".   Globals may be accessed,  but they also have undefined
initial  planning  value.   All  variables  which  have  explicit  or
implicit  assignments within a  procedure acquire  the value
"undefined" at the point directly after the procedure call.

	No modification  of the attach structure  is allowed inside a
procedure. The  compiler (often wrongly)  assumes that  there are  no
attachments involving variables within a procedure; to override this,
.UNFILL
	ASSERT FACT (ATTACHED F1 F2)   .
.REFILL
  Attachments are discussed in {ssref att}.

	There  are four  special  types  of procedure  calls:  A  HAL
program might wish to call a routine coded for the PDP11 or a routine
coded for the  PDP10. Likewise, a  program on the  PDP10 may wish  to
control a HAL program, or a routine on the  PDP11 may wish to request
some arm motion.

	To  achieve the  first  two  cases,   there  exist  "external
procedures" in HAL.  These are compiled into calls on either routines
in the PDP11 or  routines in the runtime  PDP10 package.  To  declare
such a  procedure: 
.UNFILL
	EXTERNAL PDP10 FRAME PROCEDURE FOO (FRAME A, B; VECTOR V)    .
.REFILL
 This declares the procedure FOO to be a procedure resident
in the runtime PDP10 package,  expected to return a frame  value, and
taking as arguments two frames  and a vector. PDP10 procedures do not
have access  to the  actual variables  sent, since  copies are  made;
therefore, all  arguments to  PDP10 procedures  are considered to  be
VALUE parameters.

	It  is  possible to  declare  untyped  (i.e., statement-like,
instead of expression-like) procedures as well.  Replace "PDP10" with
"PDP11" for procedures in the  PDP11. PDP11 procedures do have access
to  values, and therefore parameters are not automatically considered
to be VALUE.

	To achieve  the  second two  cases,   there  exist  "internal
procedures"  in HAL.   It is  not necessary to  state from  where the
procedure may be  called.   Internal procedures  must be  at the  top
level of a HAL program.   A complete HAL program is  considered to be
an untyped procedure without parameters.

.NEWSS (DATA STRUCTURES,DATA STRUCTURES)
.NEWSSS	DECLARATIONS.  PLANNING VALUES.  ASSERTIONS

	There are several available types of variables and constants,
as  described  below  in detail.    Each  variable  must be  declared
somewhere before it is used;  however, it is not necessary that  this
declaration be at  the top of a  block.  If a variable  which has not
been declared is encountered, an attempt will be made to guess at its
type.  (The compiler will, of course, give a  warning.) This can lead
to unfortunate results,  so it is best to  declare all variables. The
compiler keeps track  of a "planning  value" for each  variable.   At
first,  this value is "undefined"; any  expression using an undefined
value  itself has  undefined value.   Planning values  become defined
through two  mechanisms:  Assertions and  assignments.  The  statement
ASSERT X=3 will set  the planning value
of  X to 3.
(See {sssref asr} for details about assertions.)
 The statement Xα←3 has  the effect of setting the planning
value to 3 and  causing code to be  generated for the runtime  to set
the value of  X to three at this point in  the program.

The purpose  of
having planning values is severalfold,   the most important use being
the calculation  of proper trajectories.  An example is 
.UNFILL
	ASSERT YELLOW=YPARK 
.REFILL
 which tells where the yellow arm is.  Since at planning time
it is expected that some values will be known only roughly, provision
is made for the runtime  to modify all trajectories before  executing
them.  This is the subject of a  later discussion. The planning value
of any  variable is accessible to the  programmer: α#(A) is the planning
value of the expression A.

Assignments and assertions within loops pose a special problem for the
compiler. The question of when variables have good planning values
is a matter for research and debate; we have chosen this simple rule:
If a variable is neither assigned nor asserted in the loop, its
planning value stays the same as it was when the loop was begun.
Variables which have their value changed, either through assignment
or by assertion, have undefined planning value between the loop head
and the statement that changes them.
JUMPS would so complicate the planning-value computation that they
have not been implemented.

Here is an example of a loop, showing what planning values obtain
at various places:

.UNFILL
.begin
.narrow 8,8
A  α← 1;
B  α← 1;
C  α← 1;
WHILE <condition> DO
	BEGIN
	α{α#(A)=1, α#(B)=UNDEFINED, α#(C)=UNDEFINEDα}
	B α← 3;
	α{α#(A)=1, α#(B)=3, α#(C)=UNDEFINEDα}
	ASSERT C = α#(B);
	B α← 4;
	α{α#(A)=1, α#(B)=4, α#(C)=3α}
	END;
α{α#(A)=1, α#(B)=UNDEFINED, α#(C)=UNDEFINEDα}
.end
.REFILL

.dat: NEWSSS	ALGEBRAIC DATATYPES

	The simplest  datatype is  the SCALAR,   which is  internally
represented  as  a fixed-point  number.   Scalars  are  used  as time
intervals, space intervals, and as substructures upon which  the more
complicated datatypes  are built.   The UNITS  statement 
allows the  user to set the measurement system she would like to use,
so that a  time scalar will  be unambiguously interpreted as  meaning
seconds,  or jiffies, or whatever she wants. Some examples:
.UNFILL
	SCALAR A, B;
	A α← 2.4;
	UNITS CENTIMETERS, SECONDS,RADIANS; 
.COMT 12
COMMENT:  These units
		would only apply to A, for example, if A is used
		as a distance, a time, or an angle.  UNITS
		statements do not obey Algol scope, so this one
		will be in effect until the next one appears;
.END
	B α← 3*A;
.REFILL
	The next datatype  is the VECTOR.   A vector is written  as a
triple of scalars separated by commas.  An example is (2,x,4.3).
Vectors  can refer  either  to  location offsets  (that  is,
translations) or to  orientation offsets (that is,   rotations).  The
context  is  sufficient  to  determine  which  of  these meanings  is
intended. When a vector refers to a translation, it  is understood to
be in TABLE coordinates.
(TABLE is defined below.)
 When  a vector refers to a rotation,  it can
either be represented in Euler angles (rotations about z, x',   z''),
Bolles angles (rotations about  x,  y, z),   Taylor angles (rotations
about z, x', y'), or Geomed angles (a, b, c, specifying the vector of
rotation  whose magnitude  is  the  angle  of  rotation).
Note that rotations are about the table coordinate system.
  The  UNITS
statement  serves to  set a  default mode  (as well  as to  determine
whether degrees or radians are being used).
There are three predefined vector constants: X, Y, and Z.  These are
the unit vectors in TABLE coordinates.
.UNFILL
Examples:
	VECTOR V1, V2;
	V1 α← (3,1,A);
	V2 α← V1 α∂ (π,0,0);
.REFILL
	A FRAME is a location with an orientation.   It has two basic
interpretations,  which are closely related: 1) a hand position,  and
2) the location and orientation of any object.  TABLE is a predefined
frame. (It holds table coordinates.)  Each arm (currently, YELLOW and
BLUE) is also a predefined frame; these frames are "read only" in the
sense that they  may not appear to  the left of an  assignment arrow.
The values of YELLOW and BLUE are implicitly modified by arm motions,
however. The rest  positions of  the two  arms are  YPARK and  BPARK,
which are frame constants.

	Frames are described by  a pair of vectors: one  for position
and one for orientation.   An example of a frame expression is 
.UNFILL
	[LOC : ORIENT]
.REFILL
 where LOC is  a vector specifying  location, and ORIENT is  a
vector  for the  orientation  (with respect  to the  table).   
Examples:
.UNFILL
	FRAME F1, F2;
	F1 α← [V1 : V2];
	F2 α← F1 α∂ V2;
.REFILL
	A PLANE  is constructed  from two  vectors: the plane  passes
through  the first vector,   and the outward-facing normal  is in the
direction of  the second  vector. The  syntax is 
.UNFILL
	VECTOR1 α\ VECTOR2.
.REFILL
Thus, the surface of the table is (0,0,0) α\ Z.  

	Planes divide  the universe into  three sets with  respect to
the  plane: inside,  on,  and outside.   Outside are all points which
are on the side of  the plane towards the outward-facing normal.   To
determine  where a  point  lies with  respect  to a  plane, that  is,
whether it is inside,  on,  or outside the plane, use the  expression
.UNFILL
	VECTOR %5.%* PLANE   .
.REFILL
 Its value is a scalar whose absolute value  is the shortest
distance from the  vector to the plane, and whose sign is negative if
the vector is inside the plane, 0 if the vector is on the plane,  and
positive if the vector is outside the plane.

	It  is occasionally  useful to  construct a  plane from  four
scalars:  the  first three  are  the outward  pointing  normal vector
(which will be normalized  if necessary); the fourth is  the opposite
of the  distance to the  origin (of table  coordinates).  The  way to
express such a plane is like this: 
.UNFILL
	(S1,S2,S3,S4)   .
.REFILL
Examples:
.UNFILL
	PLANE P1, P2;
	P1 α← LOC(F1) α\ (X WRT F1);  COMMENT:  Y-Z plane of F1;
	P2 α← P1 + (P1.(0,0,0))*NORMAL(P1); COMMENT:  Moves P1 to origin;
	S1 α← V1 . P1;
	P1 α← (2,4,3.2,8.1);  COMMENT:  Fairly meaningless;
.REFILL
	A TRANS is an operator acting on vectors, frames, planes, and
other transes.  It is defined as the relation between two frames.  An
example is  FRAME1 α→  FRAME2.   The value  of this  trans applied  to
FRAME1  is FRAME2.   That  is,  (FRAME1α→FRAME2)*FRAME1 is identically
equal  to FRAME2.   A  trans can be  built up  from a  rotation and a
translation; the expression is 
.UNFILL
	[TRANSLATION | ROTATION]    .
.REFILL
   Note that
rotation is applied  first.  Some people find it  helpful to think of
frames as transformations: The transformation associated with a frame
A is  
.UNFILL
	TABLE α→ A    .
.REFILL
   When a  frame is used  in a context  demanding a
transformation,   it will be understood as  a shorthand for the trans
leading from the table. Transes operate on the left.  Examples:
.UNFILL
	TRANS T1, T2;
	T1 α← F1α→F2;
	V1 α← T1*V2;
	T2 α← T1*T1;
.REFILL
.NEWSSS	ARITHMETIC

	Here is  a summary of  the arithmetic  expressions available.
They  are grouped by the  type of their values.   These abbreviations
are used: `s' = scalar , `v' = vector , `f' = frame, `p' = plane, `t'
= trans.
%7
.BEGIN VERBATIM
.GROUP
scalar expressions:
s + s		scalar addition (commutative)
s - s		scalar subtraction
s * s		scalar multiplication (commutative)
s / s		scalar division
v . v		dot product of two vectors (commutative)
| v |		magnitude of vector
p . v		signed distance from vector to plane (see discussion
			above on planes)

.MAYBREAK
vector expressions:
(s,s,s)		forming a vector from three scalars
s * v		dilation of a vector
v + v		vector addition (translation of the first vector by 
			the second) (commutative)
v ∂ v		rotation of the first vector by the second
t * v		transformation of a vector
f / f		difference (rotation) between two frames
v WRT f		a vector of length |v| rotated into f's system; like
			v ∂ orient(f); that is, a vector in table
			coordinates which looks to the table as v
			does to f.

.MAYBREAK
frame expressions:
[v : v]		forming a frame from location (first vector) and
			an orientation (second vector)
f + v		translating a frame; modifies only the location part 
f ∂ v		rotating a frame; modifies only the orientation part
t * f		transformation of a frame

.MAYBREAK
plane expressions:
v \ v		formation of a plane.  Goes through first vector,
			outward pointing normal is in direction of
			the second vector.
(s,s,s,s)	formation of a plane.  First 3 scalars form outward-
			pointing normal; last scalar is opposite of
			distance to (table) origin.
p + v		translation of a plane by a vector
p ∂ v		rotation of plane (about table origin) by a vector
t * p		transformation of a plane by a trans

.MAYBREAK
trans expressions:
f → f		transformation which leads from the first frame to
			the second
[v | v]		composing a translation, then a rotation to make a
			trans.  Even though the translation is 
			written first, it is applied after the 
			rotation.
t + v		translating a trans;  modifies only the translation
			part.
t ∂ v		rotating a trans; modifies only the rotation part.
t * t		composing two transes.  Transes operate on the left.


.MAYBREAK
PREDEFINED CONSTANTS AND VARIABLES:

π is 3.14159...
TABLE is a frame which has standard table coordinates. (constant)
BLUE is the location of the blue hand.
YELLOW is the location of the yellow hand.
BPARK is where the blue hand parks. (constant)
YPARK is where the yellow hand parks. (constant)
X is (1,0,0).
Y is (0,1,0).
Z is (0,0,1).
.END
%*

Any expression preceeded with the symbol "α#" means "the planning value
of this expression", that is, a constant is substituted for the entire
expression in the expander.
.UNFILL

EXTRACTION FUNCTIONS:

LOC(FRAME) is a vector whose value is the location of the frame.
ORIENT(FRAME) is a vector whose value is the orientation of the frame.

XSCAL(VECTOR) is the X coordinate of the vector.
YSCAL(VECTOR) is the Y coordinate of the vector.
ZSCAL(VECTOR) is the Z coordinate of the vector.

NORMAL(PLANE)	is the outward facing normal vector of a plane.
.REFILL

.NEWSSS	SOME EXAMPLES OF ARITHMETIC EXPRESSIONS
.UNFILL
In the following examples, assume these declarations:
FRAME F1, F2, etc;
VECTOR V1, V2, etc;
SCALAR S1, S2, etc;
PLANE P1, P2, etc;

.MAYBREAK
F1'S unit Y vector, in TABLE coordinates:
	F1*(0,1,0)
	F1 * Y

.MAYBREAK
F1's Z vector as seen from F2:
	(F2α→F1) * (0,0,1)
	(F2α→F1) * Z

.MAYBREAK
A vector pointing in same direction as F1's X coordinate:
	X WRT F1

.MAYBREAK
V1 rotated 90 degrees about the table's Z axis:
	UNITS EULER;
	V1 α∂ (90,0,0)

.MAYBREAK
F1's Y-Z plane:
	LOC(F1) α\ (X WRT F1)

.MAYBREAK
A plane 3 units above the table:
	(0,0,3) α\ Z
	(3*Z) α\ Z
.REFILL
.NEWSS MOTIONS
.NEWSSS	COMPILE-TIME AND RUNTIME CONSIDERATIONS

	All motion statements  cause the compiler to make  some plans
for  the eventual execution of  the motion.  These  plans are more or
less complicated, depending  on the exact  type of motion  requested.
Those motions which depend on the  value of some frames as parameters
to the  action will be planned using the compile-time planning values
for all relevant frames.  

	Immediately before the arm starts moving on a trajectory, the
plan is modified to bring it into line with current values of frames.
The result of this last-minute  modification is that if there is  any
discrepancy  between the  runtime and  compile-time understanding  of
where  any frame is, the servo will place  the arm in the right place
nonetheless.  There are limits to the proper use  of this feature; if
the planning value is seriously  in error (and this can mean anywhere
from a few inches to a foot, depending on the arm being used and  its
configuration), then the attempt to make last-minute corrections will
either overstrain the arm or impair force and free sensing (discussed
below).

     It  is  the   user's  responsibility   to  foresee   such
discrepancies in the planning value and to branch her program so that
several  moves  are planned  (with  ASSERT statements  to  inform the
compiler of the  assumptions being used). The  IF-THEN-ELSE statement
will  be useful in  performing the  correct branch  at runtime.   Its
condition will most likely involve the location of a frame.
Actually, the compiler will eventually be able to do some of this
artificial splitting by using locus information and given tolerances.

	The last  step  of any  motion  is  the reevaluation  of  the
location of the hand, and the  updating, if necessary,  of the values
of all frames attached to it.

.NEWSSS	SIMPLE MOVES

	A move is simple if it involves only one  arm. 
A smooth
trajectory is  compiled by
splining   together  polynomial   segments  (usually   third  degree,
occasionally fourth)  separately for each arm joint.  This trajectory
calculation is somewhat  time-consuming,  and  is done completely  at
compile time.
The arm is expected to travel from its  current position
to the  final position,   passing through any  specified intermediate
positions.   The standard way  to avoid the table  is to begin motion
directly away from it and to end motion directly toward it.  There is
a default offset associated  with each frame,  called its "deproach",
which  is  used  to  calculate  the   first  and  the  last  of   the
intermediate, or "via" points.  The deproach of a frame  is stored in
the assertional data base, which is discussed in {sssref asr}.
	An example:
.UNFILL
	MOVE YELLOW			α{Smooth motion, for yellow armα}
		TO FROBGRASP		α{Name of (frame) destinationα}
		VIA SWING1, SWING2	α{Two via-pointsα}
.REFILL
This example demonstrates the general syntax; the reserved
word MOVE is followed by the name of the frame to be moved (usually an
arm) and a set of clauses, each beginning with a
reserved word (here the words TO and VIA).  There is no punctuation
necessary at the end of a clause.

In the example above,
The first implicit via point will be  the deproach point for whatever
frame  at which  the yellow  arm is currently  positioned.   The last
implicit via point will be the deproach point for frobgrasp.

	At  each  of  the via-points,    several  conditions  may  be
specified.  These  are velocity and upper or lower bounds on the time
required to reach this frame from the previous one on the list. Also,
one may specify that a  piece of  code is to  be initiated when a VIA
point is achieved; this is done with a THEN construct.  The statement
following THEN may not be  a jump or a motion statement for  the same
arm.  (If the statement is a motion statement, it must be surrounded
by BEGIN and END.)
	An  example:  
.UNFILL
	VIA  F1 (VEL=3*Z), F2 THEN ENABLE  "CH1",  F3 (VEL=0, DURATION=5)    .
.REFILL
This specifies three via points.  At the first, the velocity is to be
3*Z, at  the second a scalar variable is to  be set, and at the third
the velocity is to  be 0 and  it should take 5  seconds to get  there
from F2.

	Certain things must be specified for any  move.  First is the
arm  which is to be  moved.  It  can be named directly  (as YELLOW or
BLUE) or by naming a frame which is to be moved: If FROB  is attached
to a hand,   it is perfectly  reasonable to request that  the frob be
moved  to a particular location.   So if FROB is  a frame attached to
BLUE, then both FROB and BLUE are "controllable frames"; MOVE FROB is
perfectly legal. A discussion of frame attachment can be found in 
{ssref att}.

	Next, the destination  frame must be  specified. TO F1  means
that at the end  of the motion, the controllable frame  (assume it is
an  arm) should coincide with  the frame F1.   MOVE FROB  TO F2 means
that at the end of the motion,  FROB coincides with F2.  A notational
convenience about  destinations: They  can be  specified in  terms of
where  the controllable  frame is at  the start  of the  motion.  The
symbol for this is ⊗.   That is,  ⊗ is a frame which  is the location
and orientation of the controllable frame at the start of the motion.
Thus, ⊗ +  (0,0,1)  is a frame  1 unit above  the starting place  (in
table coordinates).

.NEWSSS	OPTIONS FOR MOVES

	DIRECTLY tells the compiler that only the via points and the
final point are of interest; no smooth trajectory need be planned.
A smooth motion will result due to runtime calculations.
This will also set the deproaches to NIL.
(Deproaches are discussed in {sssref dep}.)

	ON requests that certain conditions  be continually monitored
during motion.   These can be conditions  of any sort, including flag
checking,   force checking,   and time  checking.   If any  monitored
condition triggers,  the DO part associated with it will be executed.
The  "block" of  a motion-based  ON monitor  is the  motion statement
itself; exiting the motion will disable the test.  

	Several functions  can be  tested continually; these  include
force along a vector (FORCE(V)), time since beginning 
of motion
(DURATION), and
the force between the fingers (SQUEEZE).

	One more "function" is testable: ARRIVAL.   This becomes true
when  the  motion   terminates  due  to  either  having  reached  its
destination.
It does not become true if the arm stops for reasons other than normal
arrival at the destination; STOP does not trigger it.
	An example: 
.UNFILL
	ON FORCE(Z)>10 DO
		BEGIN WRITE("OUCH"); STOP END
.REFILL
	TRACING  is another  option.    It  allows the  user  greater
control over the  exact trajectory chosen for the move.  The path can
be traced at whatever  speed desired.   The path,  or  "parameterized
frame",  is  a specification of what  frame the arm is  to go through
for each  value of the parameter.  Of course,  one also specifies the
relation between the parameter and real time.  It is also possible to
state the  grain of the motion  and the tolerance  that is acceptable
(as a distance in 3-space). 
	An example:
.UNFILL
	MOVE YELLOW 
		TRACING CENTER + (COS(P),SIN(P),0)
		FOR P α← 0 UNTIL 2*π
		WITHIN .1;
.REFILL

should move the yellow arm in a circle around CENTER.

	The option  MAINTAINING ORIENTATION causes
the trajectory computed  by HAL to  try to  maintain the same
hand orientation  throughout  the motion.    Of  course,   the  final
orientation must be  the same as the initial orientation  for this to
work at all.

	USING lists a  set of modes under  which the motion is  to be
performed.   These can  include duration  control,  force  applied in
some direction,    which  directions  should be  free  from  position
feedback,   and what the departure  and approach should be  (if it is
desired to override the defaults,  which are properties of the frames
involved at the beginning and end of motion). 

	Duration  refers to  the  time  elapsed  since the  start  of
motion.  In an ON-monitor,  one can  check for duration  becoming too
long.  In the USING construct, duration is merely a note for how long
the trajectory should be  planned to take.  One can  use %7≥%*,=,or ≤ for
this, although ≤ is most likely risky.
Example:
.UNFILL
	USING DURATION %7≥%* 3    .
.REFILL

	Force specifies  both a direction  and an intensity.   During
the  motion,  an  attempt will be  made to apply  the required force.
This is done by  applying certain forces  in some combination of  arm
joints.  Which arm joints are affected is decided by the compiler; if
the motion  is long, it is likely that the particular joints applying
force will be scheduled to change during the motion, as the aspect of
the arm changes. To get a  force in the hand's Z direction, say,  one
would write 
.UNFILL
	FORCE = Z WRT @     ,
.REFILL
 where @ is a symbol meaning "the  location
of the controllable frame,  as continuously changing during motion." 

	A free  direction is  one in  which all  position errors  are
ignored  by the servo.   As for forces, the  compiler translates this
into a  set  of  joints  which  are to  have  the  position  feedback
disabled, and this  set may vary throughout the motion.   Once again,
the @ may be used to refer to the controllable frame as it moves.

	It  is possible to  free more  than one direction,   or apply
force in  more than  one direction.    In this  case, the  directions
specified  for force  must  be orthogonal,   as  must  the directions
specified for free.  This restriction is enforced by the  requirement
that  multiple forces  and  frees  all be  set  with respect  to  the
cardinal directions of one frame.  Examples:
.UNFILL
	USING FORCE = Z WRT FROB, FORCE=X WRT FROB, FREE=Y WRT HAND
	USING FORCE = (2,1,0), APPROACH = APPROACH(FROB);
		COMMENT:  This form will be explained in {sssref dep};
	USING FREE = X, FREE = Y, DEPARTURE = NIL
.REFILL
	Since both force and free are translated by the compiler into
special handling  of certain joints, surprises  can result from large
discrepancies between  the  planning values  and the  actual  runtime
values.   The  motions  will go  through the  right  places, but  the
directions of force and freedom may be wildly wrong.

	The notions  of force and  free are  hardware-dependent; they
depend   on  the  particular  arm   in  use.     Hopefully,  as  more
sophisticated arms become available, USING can be extended  to handle
whatever new capabilities exist.

.dep: NEWSSS DEPROACHES

	Many objects  have shapes which  necessitate care as  the arm
approaches  them or departs from  them.  HAL supplies  a method for
insuring that every  time the arm  approaches a  frame, it will  pass
through some  associated spot  first, and every  time it  leaves that
frame,   it passes once  again through the same spot.   The "spot" is
termed a DEPROACH  (from DEParture  and apPROACH),   and is really  a
transformation  to  be applied  to  the frame  involved  in order  to
discover the appropriate place through which to pass. The reason that
a transformation is used,  and not a frame itself, is that deproaches
are  often used  for large  objects, like the  table, and  the proper
point to pass through in that case is 10 centimeters above  where the
hand  is meant  to  arrive on  the  table (or  above  where the  hand
currently is  on the table,  if a departure is meant),  not the point
10 centimeters above the table origin.

	One  specifies  the  deproach  of  an  object  by  making  an
assertion; for  example, the deproach  of the table  is automatically
asserted as follows (see {sssref asr} concerning assertions):
.UNFILL
	ASSERT FACT (DEPROACH TABLE [(0,0,10) | (0,0,0)])   .
.REFILL
 This means
that the correct departure point  from a spot S on the  table will be
.UNFILL
	[(0,0,10) | (0,0,0)] * S    .
.REFILL

	As an  object moves about in space,  its deproach point moves
as well.   Thus 
.UNFILL
	ASSERT FACT (DEPROACH FROB [(0,10,0) | (0,0,0)]) 
.REFILL
means that  no matter  where  the frob  may  go, its  deproach  will be  10
centimeters  in the y-direction away from  its origin, as measured in
its own coordinate system.


	What if  the hand  is not  at FROB,   but wishes  to use  its
deproach?  This also is handled correctly; the deproach point will be
10 centimeters in FROB's y-direction from wherever the hand  actually
is.

	Deproaches,  being  transformations,  also have the  power to
include  rotations. These  are considered to  be rotations  about the
origin of  the coordinate system  involved; the  rotation occurs,  as
usual, before translation.  Thus
.UNFILL
	ASSERT FACT  (DEPROACH FROB  [(5,0,0) | (0,0,90)])  
.REFILL
has the effect  that whenever  FROB's deproach  is used  from any  frame, the
deproach frame will be  the given frame, rotated about  FROB's origin
by 90  degrees in Z,  and then translated  5 centimeters in  FROB's X
direction. 


	Suppose that a frame
F  is given  deproach transformation D.   It  is desired to  find the
frame which  is  the deproach  point from  some  other frame  H  (for
example, where the hand is, for  departure), using F's deproach.  The
frame  which  is  used  is 
.UNFILL
	F  *  D  * (Fα→TABLE)  *  H    .
.REFILL

If H = F, then the identities 
.UNFILL
	(F α→ TABLE) * F = TABLE, and X * TABLE =X     .
.REFILL
reduce the expression for F's deproach to F * D.

	When an arm moves to a frame, this is how the deproach point
is calculated:  The frames own deproach is used, if it has one.  If
not, then a search is made up the ladder of attachment (that is, frames
to which the given frame is attached are searched) until one is found
with a deproach.  
If none  at all is found,  then the table's
deproach is  used as a  default.   (One way  to think of  this is  to
consider all frames ultimately  attached to the table.) In approaching
a frame which  is  the  result of a  calculation (such as  MOVE
YELLOW TO FROB + (0,0,1)) the default deproach is null.
The default deproach of ⊗ is also null.

	In departing from a frame,  it  matters whether or not that frame is
now attached to the hand.  If not, then the same algorithm for
finding deproach is used as in the case of approach. But if the frame
has been detached  from some erstwhile mother and is  now attached to
the  hand,  then its  old mother's deproach is used  (and if there is
none, the same search is  made).  
A frame
attached to the hand still has some "memory" of its previous state of
attachment, by means of an automatic WAS_ATTACHED assertion 
which will be mentioned in {ssref att}.

	All of  the automatic generation  of deproach  points can  be
explicitly overridden in a MOVE  statement by means of the USING
clause.  This can take two forms:
.UNFILL
	USING  APPROACH = NIL;  COMMENT: No approach point  at all is used;
	USING APPROACH = DEPROACH(frob); COMMENT: frob's  deproach is used;
.REFILL

	Note that the word  APPROACH could be replaced by DEPROACH in
both of the examples above.
.NEWSSS	COMPLEX MOVES

	A complex move is  one which involves more than one  arm at a
time.  A distinction can be  made between moves  which merely require
simultaneous acquisition of "agreement points" (let us call this weak
synchrony),  and   those  which   require  true   coordinated  motion
throughout (strong synchrony).

	Weak synchrony is achieved by pairing frames to make composite
VIA points and destinations.  A paired frame  has the form: α{F1, F2α}.
Here is an example of a move statement using paired frames:
.UNFILL
	MOVE α{YELLOW, BLUEα}
		VIA α{Y1,B1α},α{Y2,*α},α{Y3,B2α}
		TO α{Y4,B3α}
		ON α{FORCE(Z)>3,*α} DO STOP
.REFILL
	The via list is  composed of a set of paired  frames, where *
indicates  "don't  care".   In  the  example  shown,  the arms  start
together, achieve  Y1 and B1  simultaneously, the  yellow arm  passes
through Y2, and together they pass through Y3 and B2.  

	It  is  now  more  cumbersome  to  specify  ON  monitors,  or
conditions  in general.   The  paired construct  applies for  all the
optional fields; thus, one can write
.UNFILL
	USING FORCE=α{3*Z,(2*Y) WRT @α}
.REFILL
  to get the  yellow arm applying  a
force of strength 3*Z, and the blue one to have a force of strength 2*Y
in the coordinate system of the blue hand.

	The meaning of ⊗ and @ is  now relative to which side of  the
pair they occupy; in  the example above, the left  side always refers
to the yellow arm,  and the right side to the blue.  To override this
convention, one may use expressions like "@.YELLOW", or "⊗.BLUE".

	The meaning of STOP in the example above is extended  to both
arms at once;  in order to specify  only one, it is  necessary to say
"STOP YELLOW" or "STOP BLUE".

	Strong synchrony involves one concept not included above: The
ability to  specify the location of one  arm throughout the motion in
terms of the location of the  other arm.  The construct which  allows
this  specification  is  COORDINATING;  it allows  one  to  give  an
expression for  the location of one of the two arms.  Suppose we wish
to keep both arms in "lockstep", that is, the  blue arm should retain
its relative position to the yellow arm throughout the motion.  (This
might be necessary for lifting some object by its two ends.) One  way
to code this task is as follows:
.UNFILL
	MOVE α{YELLOW, BLUEα}
		TO α{Y1, *α}
		VIA α{YA,BAα},α{YB,BBα}
		COORDINATING LOC.BLUE = LOC.YELLOW + ⊗.BLUE - ⊗.YELLOW
		USING FREE = α{*, @.YELLOW - @.BLUEα}
		α{MAINTAINING ORIENT, MAINTAINING ORIENTα}

.REFILL
.NEWSSS SEARCHES

	A  SEARCH is  very  much like  a  move.   It  is a  means  of
specifying  repeated action  in a  spiral.  As  with a  MOVE,   it is
necessary to name a controllable frame which is to be moved.   The ON
construct is exactly as for MOVEs.

	One must  stipulate what the  plane of  the search is  to be.
This is  accomplished in either of two ways: ACROSS <plane> means the
search is to take place in the plane specified.   If the controllable
frame (say, the hand) is in  fact not in that plane at the start, then
the plane parallel to the given one through the hand will be used. It
is assumed  that the  hand begins at  the center  of the search.  The
other  alternative is to say  NORMAL_TO <vector>.   This,
together with the location of the hand,
 will specify
the plane you want for the search.

	The size of the increment is specified in a  USING construct.
An example is USING INCREMENT = 3.

	The servo does almost all the calculating for searches; it is
fed the normal direction and the increment size.

	Most important  for the search is the REPEATING construct, which
specifies what motion is to  be performed at each
iteration.  It is advisable that  the motion cause the
arm to return to the point at which it began, in order to assume  the
same plane at the onset of each iteration.  If this is not done, then
the  servo will  move  it back  each time  anyway.   When  the search
succeeds (and it  is the  duty of  the user to  specify what  success
means for each search) the search  can be terminated in either of two
ways: by  setting a flag in the REPEATING and checking it with an ON,
or by  using the  construct TERMINATE inside  the REPEATING  at the  right
place.
	Here is a complete example:
.UNFILL
	SEARCH YELLOW
		ACROSS P1
		REPEATING 
			BEGIN
			FRAME SET;
			SET α← YELLOW;
			MOVE YELLOW TO ⊗-Z
				ON FORCE(Z) > 3 DO TERMINATE;
			MOVE YELLOW TO SET DIRECTLY;
			END
.REFILL

.NEWSSS	CENTER

	Occasionally the hand is positioned around an object, but it
is not certain if it is centered.  One wants to close the fingers
slowly, moving the arm meanwhile to accomodate to the location of
the object.  
This  is accomplished by means of the CENTER command.
The direction that the hand will move is the direction between its
fingers.  All that the CENTER command needs is the name of the
arm being moved.
The use of  ON is just  as in  a
search or any other motion.

	Here is a simple example:
.UNFILL
	CENTER BLUE
		ON SQUEEZE > 4 DO STOP
.REFILL
Note that this is command, unlike MOVE, treats the fingers and
the arm together as one device.

.NEWSSS	CONSTANT VELOCITY MOTION

	A special form of the MOVE instruction is provided
to cause  the arm to  quickly achieve a  particular velocity,
and to hold it in straight-line motion for a given distance:
.UNFILL
	MOVE YELLOW
		VELOCITY=V1
		THROUGH T
		FOR DISTANCE=4		.
.REFILL
The VELOCITY clause tells which  vector to follow,  and how  fast. The
THROUGH clause tells the compiler where the move  expects to end. The FOR
DISTANCE tells the maximum distance the hand should go. It is assumed
that such a move will normally terminate by an ON test.
For example:
.UNFILL
	MOVE YELLOW
		WITH VELOCITY=V1
		THROUGH T
		FOR DISTANCE=4
		ON FORCE(V1) > 2 DO STOP
.REFILL

.NEWSSS DEVICE CONTROL

	Generally, an arm will  stop its motion when it  has achieved
its destination.   Often it is necessary  to stop it prematurely, for
example, if some  error condition  is detected.   The statement  STOP
YELLOW causes the  yellow arm to be unconditionally  stopped, and any
motion statement operating it will terminate. Each device has a name,
and can be  stopped by name.   Currently, the legal device  names are
YELLOW,  BLUE,   VICE,  DRIVER (an  electric  screwdriver), YFINGERS,
BFINGERS (The fingers of the two arms). STOP without any device  name
is only legal within a motion command;  it stops whatever device(s) that
command is operating.

	There is a  general command for operating devices  other than
arms; it is hoped that this will be flexible enough for any device we
are likely to use (if not, we will add special new forms).  Assume we
have the device TURNTABLE, which is capable of moving at any velocity
and  for any length of time, but which  cannot go to a particular set
point.  Then the syntax would be this:
.UNFILL
	OPERATE TURNTABLE
		WITH VELOCITY=3
		WITH DURATION=8
.REFILL
The idea is that  the WITH construct will suffice to  account for any
special  data (in this case,  velocity and duration)  peculiar to the
particular  device.    The  OPERATE  statement  also  allows  the  ON
construct, so it can test for special conditions and take appropriate
actions.

	The screwdriver is a  hand-held device which can be  run at a
range  of speeds,  in either  direction.   By convention,  a positive
velocity   means   clockwise,   and   a   negative   velocity   means
anticlockwise.  The  relevant reserved  word  is  VELOCITY, which  is
equated  with the name  of a  scalar variable, which  will be queried
each time  the  screwdriver  servo wakes  up  to determine  how  much
voltage  to apply to the  motor.   This allows  the velocity  to change
during the operation of  the device, perhaps under  the control of  a
parallel process which is monitoring some conditions.
	An example:
.UNFILL
	OPERATE DRIVER
		WITH VELOCITY=SP
		ON DURATION>4 DO STOP
		ON DURATION>2 DO SP α← 2*SP

.REFILL

	Each arm  has two  fingers at  the end  which are capable  of
closing and  opening at various speeds.   The relevant reserved words
are OPENING, which is to be set to the desired (scalar) opening,  and
VELOCITY, which is to be set to the speed desired.  It is possible to
refer to the scalar variable SQUEEZE, which indicates the force being
applied by the fingers.
	An example:
.UNFILL
	OPERATE FINGERS
		WITH OPENING=4
		WITH VELOCITY=2
		ON SQUEEZE > 3 DO STOP
.REFILL

.att: NEWSS ATTACHMENT

	Assembly often involves affixing  one object to another.  HAL
has a mechanism to automatically keep  track of the location of  a
subsidiary piece of the assembly as its  base is moved; the mechanism
is  called attachment.   For example, there  might be  a frame called
PUMP and a  frame called BASE.   At some stage  in the assembly,  the
pump  is bolted  to the  base.   At this  time it  is appropriate  to
include the statement 
.UNFILL
	ATTACH PUMP TO BASE
.REFILL
 The  effect of  this is  severalfold: It  informs the compiler  that
motions of BASE  are to affect the location of PUMP, it generates the
assertion 
.UNFILL
	ASSERT FACT (ATTACHED PUMP BASE)
.REFILL
 and  it  causes code  to be  generated  for the  runtime which  will
automatically  update the value of  PUMP every time  BASE is changed.
Please note  that the  ATTACH statement  does not  act  as a  library
routine invocation; it does not generate code to actually perform the
bolting operation.   The statement merely informs the HAL system that
at  this stage  in  the  execution of  the  program,  PUMP is  to  be
considered attached to BASE.

	If PUMP  should be moved while attached to BASE, the value of
BASE itself will not change,  but the attachment will remain  for the
new relative positions of PUMP  and BASE.  Occasionally it is desired
that the attachment be symmetric, so that motion of either frame will
cause the other to move.  This is done by including the reserved word
RIGIDLY in the attach statement: 
.UNFILL
	ATTACH PUMP TO BASE RIGIDLY
.REFILL
A more precise definition of attachment in terms of graph structures
is given in {sssref  gat}.  Here, we should point out that the
system uses a trans to store the relative positions 
(in our example, "(BASE α→ PUMP)" ) of the 
attached frames.  Normally, the system would invent a 
temporary variable to hold this trans; however, the user can 
supply her own variable to be used instead, thus allowing her
to modify directly the attachment relation.  This is done by including
the phrase "BY <transform variable id>" in the ATTACH statement.
For instance,
.UNFILL
	ATTACH PUMP TO BASE BY T1;
.REFILL
	If the value of  the trans is modified  in a non-rigid  (that
is,  assymetric)  attachment,  the  effect is to move  the subsidiary
frame.   If  the value  of the  trans  changes in  a rigid  
(symmetric) attachment, then neither frame will change its value until
one of them  explicitly gets a new value; at that time the other will spring
to a new position, as determined by the trans.

The inclusion of the construct "AT <transform expression>" will cause
HAL to use the indicated value for the relative attached position of the
objects.  Thus,

.UNFILL
	ATTACH PUMP TO BASE AT [(0,0,0)|(0,0,0)]

.bull
is equivalent to

	ATTACH PUMP TO BASE BY TEMPXF;
	TEMPXF α← [(0,0,0)|(0,0,0)]
.REFILL
	It  is  possible to  make  chains of  attachments,   possibly
involving some rigid attachments and some non-rigid ones.


Attachments are undone by the DETACH statement.  For example,
.UNFILL
	DETACH  PUMP  FROM BASE
.REFILL
will remove the attach structure between PUMP and BASE,  and will discard
the invented trans  (unless it was named, of course).  Two changes in
the compiler's assertional data base will also  be generated
(See the section on assertions):

.unfill
	DENY  FACT  (ATTACHED  PUMP BASE);
	ASSERT FACT (WAS_ATTACHED PUMP BASE)
.REFILL

The latter assertion
is  used in calculation of default  deproach points. A side-effect of
any  assignment,  like F1  α←  <value>,  is  
.UNFILL
	DENY FACT (WAS_ATTACHED ANYTHING F1);
	DENY FACT (WAS_ATTACHED F1 ANYTHING)     .
.REFILL

.gph:NEWSS GRAPH STRUCTURES

Attachments are  stored in  both the  compiler and  the runtime as  a
graph structure.  The nature of this structure is described 
in {sssref rgf};
the algorithms  which serve to  extract values  from a graph  and
insert new values into  it
can be found in Appendix II.
Suffice it here to say  that if the value
of  a variable is needed,  and that  value is marked as invalid, then
the list of calculator expressions for that variable  is searched for
one which can compute a  valid value; if none of the calculators will
work
(e.g. they all depend themselves on invalid values),
 then the current (invalid) value is returned as the best answer
available. When  a new  value is  assigned to  a variable, all  those
values  whose  calculators depend  on  the new  value  are  marked as
invalid,  so that the next time they are needed,  graph  searching is
performed. Building  a graph  structure therefore  involves specifying
the  calculators for all  variables.   Usually, this will  be be done
implicitly by means  of "intuitively obvious" statements  like ATTACH
and  DETACH.   However,   HAL also  supplies primitives  for explicit
manipulation of  graph  structure.    The  principal  explicit  means
employed for this purpose is the "graph assignment statement":
.UNFILL
	<variable> <= <expression>
.REFILL
where "<="  may  be read  "is computed  by".   This construct  causes
<expression>  to be added to  the list of  calculators for <variable>.
Similarly, 
.UNFILL
	<variable> <%7≠%* <expression>
.REFILL
causes <expression> to be removed from the list of calculators, and 
.UNFILL
	<variable> <<= <expression>
.REFILL
replaces the current calculator list for <expression>. The statement
.UNFILL
	<variable> <<= ;
.REFILL
would cause the calculator list to be set to null. 

It is frequently very inconvenient to retype an entire  expression in
order to remove it from the calculator  list.  HAL allows the user to
attach a name to an expression in a graph assignment statement by use
of the construct
.UNFILL
	<variable> <= "id" <expression>
.REFILL
Then the construct
.UNFILL
	<variable> <%7≠%* "id"
.REFILL
will remove  the  named expression  from the  calculator  list.   For
instance,
.UNFILL
	F1 <= "foo" T*F2;
	:
	F1 <%7≠%* "foo";
.REFILL
would have the same effect as
.UNFILL
	F1 <= T*F2;
	:
	F1 <%7≠%* T*F2;
.REFILL
In addition to the calculator  list,  a list of "updater" routines is
associated with every variable.  These routines are executed whenever
the variable value  is changed.   Initially, the list of  updaters is
null.  However, the construct
.UNFILL
	WHEN CHANGING <variable> ALSO DO "<id>" <statement>;
.REFILL
will  cause  <statement> to  be added  to  the list  of  updaters for
<variable>. ("<id>" is optional, but is necessary if  the <statement>
is ever  to be removed from  the updater list.) In  <statement>,  the
reserved  words OLD and NEW may  be used to refer  to the old and new
values of var, respectively.  For instance:
.UNFILL
	WHEN CHANGING F2 ALSO DO "foo" F1α←NEW*(OLDα→F1);
.REFILL
Updaters may be removed from the updater list by the statement
.UNFILL
	WHEN CHANGING <variable> DONT DO "<id>"
.REFILL
For our above example, this would be
.UNFILL
	WHEN CHANGING F2 DONT DO "foo";
.REFILL
The form 
.UNFILL
	WHEN CHANGING <variable> ONLY DO <statement>; 
.REFILL
replaces the updater list with one containing just <statement>, and
.UNFILL
	WHEN CHANGING <variable> ONLY DO ;
.REFILL
clears the updater list completely.  Since the attach structure makes
use of updater and calculator  lists (see {sssref rgf}), careless use of the
replacement form is not advised.

One good use for updater routines is tracing.  For example,
.UNFILL
	WHEN CHANGING V ALSO DO
		WRITE("The value of V is now ",NEW);
.REFILL
Details of the  graph structure algorithms  may be found  in the appendix
on runtime routines.
One  additional point that should be  mentioned here is that the
updater routines  for a  variable are  NOT called  if the  variable's
value is modified  as a side effect  of a change to  some variable in
one of its calculators.

.gat: NEWSSS CONCERNING ATTACH AND DETACH

The ATTACH and DETACH statements are defined by their effects on  the
graph structures.
.UNFILL
	ATTACH F1 TO F2 BY T1
.UNFILL
is equivalent to
.REFILL
	T1 α← F2α→F1;
	F1 <= "xxx" T1 * F2;
	WHEN CHANGING F1 ALSO DO "yyy" T1α←(F2α→NEW);
	ASSERT FACT (ATTACHED F1 F2 T1); 
	       Comment : For details of ASSERT see {sssref asr};
.REFILL
Then, 
.UNFILL
	DETACH F1 FROM F2;
.REFILL
is equivalent to 
.UNFILL
	F1 <%7≠%* "xxx";
	WHEN CHANGING F1 DONT DO "yyy";
	DENY FACT(ATTACHED F1 F2 ANYTHING);
	ASSERT FACT (WAS_ATTACHED F1 F2);
.REFILL

Similarly,
.UNFILL
	ATTACH F1 TO F2 BY T1 RIGIDLY
.REFILL
is equivalent to
.UNFILL
	T1 α← F2α→F1;
	F1 <= T1 * F2;
	F2 <= INVERSE(T1) * F1     .
.REFILL